import wx
import os

from pyeasyaccept.gui.PyEasyAcceptCmdsPanel import PyEasyAcceptCmdsPanel
from pyeasyaccept.gui.UserAppCmdsPanel import UserAppCmdsPanel
from pyeasyaccept.gui.ScriptLinePanel import ScriptLinePanel
from pyeasyaccept.gui.ScriptPreviewPanel import ScriptPreviewPanel
from pyeasyaccept.gui.ChooseFacadePanel import ChooseFacadePanel
from pyeasyaccept.commom.Configuration import Configuration
from pyeasyaccept.commom.FacadeFactory import FacadeFactory
from pyeasyaccept.gui.ErrorMsg import ErrorMsg
from pyeasyaccept.gui.CommandsDictionary import CommandsDictionary

class CreateTestsFrame(wx.Frame):
    """
    This class represents a frame that allows to create a script test with a lot of
    facilities
    
    @author: Artur Farias
    """
        
    CHOOSE_FACADE_ID = 201
    USER_APP_CMD_ID = 202
    PREVIEW_ID = 203
    SCRIPT_LINE_ID = 204
    PEA_CMDS_ID = 205
    
    OPEN_ID = 301
    SAVE_ID = 302
    SAVE_AS_ID = 303
    CLOSE_ID = 304
    RUN_TEST_ID = 305
    NEW_ID = 306
    
    YES_ID = 401
    NO_ID = 402
    CANCEL_ID = 403
    
    def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize):
        """
        Initializes a RunTestsFrame with all the components needed to create the scripts tests.
        @param parent: the Frame parent.
        @param id: the Frame id.
        @param title: the Frame title.
        @param pos: the Frame initial position.
        @param size: the Frame initial size.  
        """
        wx.Frame.__init__(self, parent, id, title, pos, size)
        
        self.createMenu()
        self.SetIcon(wx.Icon(Configuration.INSTALL_DIR + Configuration.ICONS_LOCATION + Configuration.FILE_SEPARATOR + 'IconPEA.ico', wx.BITMAP_TYPE_ICO))
        
        self.panel = wx.Panel(self, -1)
        
        self.chooseFacade = ChooseFacadePanel(self.panel, self.CHOOSE_FACADE_ID, [0,0], False)
        self.chooseFacade.addListener(self)
        self.userCmds = UserAppCmdsPanel(self.panel, self.USER_APP_CMD_ID)
        self.preview = ScriptPreviewPanel(self.panel, self.PREVIEW_ID)
        self.preview.addListener(self)
        cmdsDictionary = CommandsDictionary()
        self.scriptLine = ScriptLinePanel(self.panel, self.SCRIPT_LINE_ID, cmdsDictionary)
        self.scriptLine.setCmdsDictionary(cmdsDictionary)
        self.peaCmds = PyEasyAcceptCmdsPanel(self.panel, self.PEA_CMDS_ID)
        self.peaCmds.addButtonPressedListener(self.scriptLine)
        self.userCmds.addButtonPressedListener(self.scriptLine)
        self.scriptLine.addListener(self.preview)
                
        vbox = wx.BoxSizer(wx.VERTICAL)
        
        hbox0 = wx.BoxSizer(wx.HORIZONTAL)
        hbox0.Add(self.chooseFacade, 1, wx.ALIGN_LEFT)
        
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        hbox.Add(self.scriptLine, 1)
        
        self.hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        self.hbox2.Add(self.peaCmds, 1, wx.ALL | wx.EXPAND)
        self.hbox2.Add(self.preview, 4, wx.CENTER | wx.EXPAND)
        self.hbox2.Add(wx.StaticText(self.panel, -1, '   '), 0)
        self.hbox2.Add(self.userCmds, 1, wx.RIGHT | wx.EXPAND)
        
        hbox3 = wx.BoxSizer(wx.HORIZONTAL)
        hbox3.Add(wx.Button(self.panel, self.SAVE_ID, 'Save'), 1)
        self.runTestButton = wx.Button(self.panel, self.RUN_TEST_ID, 'Run This Test') 
        hbox3.Add(self.runTestButton, 1)
        
        self.runTestButton.Bind(wx.EVT_BUTTON, self.onRunTest)
        self.Bind(wx.EVT_BUTTON, self.OnSave)

        vbox.Add(hbox0, 0, wx.ALIGN_CENTRE)
        vbox.Add(hbox, 1, wx.ALIGN_CENTRE)
        vbox.Add(self.hbox2, 3, wx.ALIGN_LEFT)
        vbox.Add(wx.StaticText(self.panel, -1, '   '), 0)
        vbox.Add(hbox3, 1, wx.ALIGN_CENTRE)
        
        self.setBackGroundColour(Configuration.BACKGROUND_COLOUR)
        
        
        self.panel.SetSizer(vbox)
        
        self.Bind(wx.EVT_CLOSE, self.OnQuit)
        
        box = wx.BoxSizer(wx.VERTICAL)
        box.Add(self.panel, 0, wx.ALIGN_CENTER)
        self.SetSizer(box)
        self.Centre()
        self.SetAutoLayout(True)
        self.Layout()
        
        self.askBeforeCloseProject = False
        self.filename = None
        self.listeners = []
        
    def setBackGroundColour(self, colour):
        self.peaCmds.SetBackgroundColour(Configuration.BACKGROUND_COLOUR)
        self.userCmds.SetBackgroundColour(Configuration.BACKGROUND_COLOUR)
        self.scriptLine.SetBackgroundColour(Configuration.BACKGROUND_COLOUR)
        self.chooseFacade.SetBackgroundColour(Configuration.BACKGROUND_COLOUR)
        self.panel.SetBackgroundColour(Configuration.BACKGROUND_COLOUR)
        self.SetBackgroundColour(Configuration.BACKGROUND_COLOUR)        
        
    def createMenu(self):
        """
        Method that creates a menu
        """
        menuBar = wx.MenuBar()
        file = wx.Menu()
        file.Append(self.NEW_ID, '&New')
        file.Append(self.OPEN_ID, '&Open')
        file.Append(self.SAVE_ID, '&Save')
        file.Append(self.SAVE_AS_ID, '&Save As...')
        file.AppendSeparator()
        file.Append(self.CLOSE_ID, '&Exit')
        menuBar.Append(file, '&File')
        self.SetMenuBar(menuBar)
                
        self.Bind(wx.EVT_MENU, self.OnNew, id=self.NEW_ID)
        self.Bind(wx.EVT_MENU, self.OnOpen, id=self.OPEN_ID)
        self.Bind(wx.EVT_MENU, self.OnSave, id=self.SAVE_ID)
        self.Bind(wx.EVT_MENU, self.OnSaveAs, id=self.SAVE_AS_ID)
        self.Bind(wx.EVT_MENU, self.OnQuit, id=self.CLOSE_ID)
        
    def OnNew(self, event):
        if not self.confirmClosingProject():
            return         
        self.scriptLine.reset()
        self.chooseFacade.reset()   
        self.preview.clear()
        self.userCmds.reset()
        self.askBeforeCloseProject = False
        self.Layout()
        
    def OnOpen(self, event):
        """
        Method that open a dialog to open a script test on click 'open' at menu
        """
        if not self.confirmClosingProject():
            return            
        filename = self.chooseFileToOpen()
        if filename != None:
            self.open(filename)

    def open(self, filename):
        """Method that open a script test"""
        file = open(filename, 'r')
        lines = file.readlines()
        self.preview.clear()
        for line in lines:
            self.preview.appendText(line)
        file.close()
        self.filename = filename
        self.askBeforeCloseProject = False

    def confirmClosingProject(self):
        if not self.askBeforeCloseProject:
            return True
        confirmation = self.askConfirmationToClose()
        if confirmation == self.YES_ID:
            self.OnSaveAs(None)
                    
        if confirmation == self.CANCEL_ID:
            return False
        else:
            return True        
        
    def askConfirmationToClose(self):
        dlg = wx.MessageDialog(self, 'Your testing project has been modified. Save changes?', 'Save Project', wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
        answer = dlg.ShowModal()
        if answer == wx.ID_YES:
            confirmationResult = self.YES_ID
        elif answer == wx.ID_NO:
            confirmationResult = self.NO_ID
        else:
            confirmationResult = self.CANCEL_ID
        dlg.Destroy()
        return confirmationResult
            
    def addListener(self, listener):
        """
        Adds a listener to this frame.
        """
        self.listeners.append(listener)
        
    def onRunTest(self, event):
        if self.askBeforeCloseProject:
            dlg = wx.MessageDialog(self, 'Your new script test is not saved. Please, save it before going on.', 'Save Project', wx.OK|wx.ICON_INFORMATION)
            dlg.ShowModal()
            dlg.Destroy()
            self.OnSaveAs(None)
            if self.askBeforeCloseProject:
                return
        facade = self.chooseFacade.getFacade()
        script = self.filename
        if not self.isValidFacade(facade):
            ErrorMsg(self, ErrorMsg.FACADE_NOT_VALID)
        elif not self.isValidScriptTest(script):
            ErrorMsg(self, ErrorMsg.SCRIPT_NOT_VALID)
        else:
            self.fireNotifyRunTest(facade, script)
        
    def fireNotifyRunTest(self, facade, script):
        for listener in self.listeners:
            listener.notifyRunTest(facade, script)
        
        
    def OnSave(self, event):
        """Method that save the file on click 'save' at menu or the button"""
        if self.filename == None:
            self.OnSaveAs(None)
        else:
            self.save(self.filename)
        
        
    def OnQuit(self, event):
        """Method that close the window on click 'exit' at menu"""
        if not self.confirmClosingProject():
            return        
        self.Destroy()        

    def OnSaveAs(self, event):
        """Method that open the dialog for save the file on click 'saveAs' at menu"""
        self.filename = self.chooseFileToSave()
        if self.filename != None:
            self.save(self.filename)
        
    def save(self, filename):
        """Method for save the script test"""
        file = open(filename, 'w')
        text = self.preview.getText()
        file.write(text)
        file.close()
        self.askBeforeCloseProject = False
        
    def chooseFileToOpen(self):
        """Method to choose a file to open and edit it"""
        projectPath = os.getcwd() + Configuration.FILE_SEPARATOR + ".." + Configuration.FILE_SEPARATOR + ".." + Configuration.FILE_SEPARATOR + ".."

        dlg = wx.FileDialog(self, "Open", projectPath, "", "*.txt", wx.FD_OPEN)
        path = None
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
        dlg.Destroy()
        return path             
        
    def chooseFileToSave(self):
        """Method to choose where the file will be save"""
        projectPath = os.getcwd() + Configuration.FILE_SEPARATOR + ".." + Configuration.FILE_SEPARATOR + ".." + Configuration.FILE_SEPARATOR + ".."

        dlg = wx.FileDialog(self, "Save As", projectPath, "", "*.txt", wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
        path = None
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
        dlg.Destroy()
        return path
    
    def isValidFacade(self, facade):
        """Method that returns if the facade is valid or not"""
        return facade != None and facade != ''
    
    def isValidScriptTest(self, scriptTest):
        return scriptTest != None and scriptTest != ''
    
    def notifySetFacade(self, facade):
        self.setFacade(facade)
        
    def setFacade(self, facade):
        """Method that set the Facade"""
        if not self.isValidFacade(facade):
            ErrorMsg(self, ErrorMsg.FACADE_NOT_VALID)
            return
            
        try:
            facadeInstance = FacadeFactory().getFacadeInstance(facade)
            self.makeUserCmds(facadeInstance)
            self.scriptLine.getCmdsDictionary().setUserAppFacade(facadeInstance)
            self.chooseFacade.setFacade(facade)
        except Exception, e:
            ErrorMsg(self, ErrorMsg.FACADE_NOT_FOUND)
            return
    
    def makeUserCmds(self, facadeInstance=None):
        if self.userCmds != None:
            self.hbox2.Remove(self.userCmds)
            self.userCmds.Destroy()
        self.userCmds = UserAppCmdsPanel(self.panel, self.USER_APP_CMD_ID, facadeInstance)
        self.userCmds.addButtonPressedListener(self.scriptLine)
        self.hbox2.Add(self.userCmds, 1, wx.RIGHT | wx.EXPAND)
        self.Layout()
        self.hbox2.Layout()
        
    def notifyScriptModified(self):
        """
        Notifies Script Modified Event.
        """
        self.askBeforeCloseProject = True